package emulator.hardware.io;

import java.util.LinkedList;

import emulator.hardware.HwNumber;
import emulator.hardware.bits.SharedBit;

public class Port6522 {

	public static final int NUM_PORT_BITS = 8;
	public static final int NUM_CONTROL_BITS = 2;
	
	private SharedBit[] out_port_bit = new SharedBit[NUM_PORT_BITS];
	private SharedBit[] in_port_bit = new SharedBit[NUM_PORT_BITS];
	private SharedBit[] control_bit = new SharedBit[NUM_CONTROL_BITS];
	
	private int mask;

	private LinkedList<Port6522Listener> listener_list = new LinkedList<Port6522Listener>();

	public Port6522()
	{
		for (int i = 0; i < NUM_PORT_BITS; i++)
		{
			out_port_bit[i] = new SharedBit();
			out_port_bit[i].setValue(true);
			in_port_bit[i] = new SharedBit();
			in_port_bit[i].setValue(true);
		}
		for (int i = 0; i < NUM_CONTROL_BITS; i++)
			control_bit[i] = new SharedBit();
	}
	
	public SharedBit getOutPortBit(int i) {
		return out_port_bit[i];
	}

	public SharedBit getInPortBit(int i) {
		return in_port_bit[i];
	}

	public void setOutPortBit(int index, SharedBit bit) {
		out_port_bit[index] = bit;
	}

	public void setInPortBit(int index, SharedBit bit) {
		in_port_bit[index] = bit;
	}

	public void setControlBit(int index, SharedBit bit) {
		control_bit[index] = bit;
	}

	public SharedBit getControlBit(int i) {
		return control_bit[i];
	}

	public void setPortMask(int mask) {
		this.mask = mask;
	}

	public int getPortMask() {
		return mask;
	}

	public void writePort(int value) {
		HwNumber hw_mask = HwNumber.create(mask);
		HwNumber hw_value = HwNumber.create(value);
		for (int i = 0; i < NUM_PORT_BITS; i++)
			if (hw_mask.getBit(i))
				out_port_bit[i].setValue(hw_value.getBit(i));
	}

	public int readPort() {
		return (SharedBit.getBits(in_port_bit) & ~mask)
			|  (SharedBit.getBits(out_port_bit) & mask);
	}

	public void pre() {
		for (Port6522Listener l : listener_list)
			l.handlePre(this);
	}

	public void post() {
		for (Port6522Listener l : listener_list)
			l.handlePost(this);
	}

	public void addPortListener(Port6522Listener port_listener) {
		listener_list.add(port_listener);
	}
}
